﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Collections;

namespace DataMining
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private DataTable samples;
        private DataTable testsamples;
        
        TreeNode root;
        private Attribute[] attributes;
        private string attributeSelectionMethod = "gain";//属性选择度量模式
        private static int total = 0;
        private static int right = 0;
        private static int wrong = 0;
        private static double average = 0;
        private void Form1_Load(object sender, EventArgs e)
        {
            tvDecision.Visible = false; //
        }
       public int txtHigh; //txt行数
       public int txtWidth;//txt列数
       public  string[,] cellData = new string[15000, 32]; //单元数据
       public static string[] strResult; //结果数组
        private void button1_Click(object sender, EventArgs e)
        {   //清空Tree控件
            if (this.tvDecision.Nodes.Count != 0)
                this.tvDecision.Nodes.Clear();
            //清空控件
            richTextBox1.Text = "";
            OpenFileDialog openFile = new OpenFileDialog();//创建打开文件对话框对象
            openFile.Filter = "文本文件|*.txt";
            if (openFile.ShowDialog() == DialogResult.OK) //执行ShowDialog方法，返回OK，没有选定则无返回，则其他界面是假死状态
            {
                this.textBox1.Text = openFile.FileName.ToString();//获取文件 value.Tostring 返回为string
                //开启读取数据线程
                Thread ReadTextFile = new Thread(ReadText);
                ReadTextFile.IsBackground = true;
                ReadTextFile.Start();
            }
        }


        //读取txt文件数据
        private void ReadText()
        {
            string[] strWidth;
            string[] strArr = RollCall(textBox1.Text);
            txtHigh = strArr.Length;//获取行的个数
            for (int i = 0; i < strArr.Length; i++)
            {
                string str = System.Text.RegularExpressions.Regex.Replace(strArr[i], @"\s+", ","); //","替换空格串
                strWidth = str.Split(','); //分割行字符串
                for (int j = 0; j < strWidth.Length; j++)
                {
                    cellData[i, j] = strWidth[j];
                }
                txtWidth = strWidth.Length;//获取列的个数

            }
            this.richTextBox1.Text += "数据数：" + txtHigh + "条" + "\n";
            this.richTextBox1.Text += "属性数：" + txtWidth + "个" + "\n";
        }


        //读取txt所有行数据
        private string[] RollCall(string path)
        {
            string[] strArr = File.ReadAllLines(path);
            return strArr;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            strResult = gainAttributeValue(txtWidth);

               samples = getDataTable();//产生用于存储训练集的数据表
               testsamples = getDataTable();//产生用于存储训练集的数据表
                for (int i = 0; i < 10; i++)
                {
                fillData(i);//填入数据
                attributeValue();//填入各属性中的属性值
                //清空Tree控件
                if (this.tvDecision.Nodes.Count != 0)
                    this.tvDecision.Nodes.Clear();
                DTree_ID3 id3 = new DTree_ID3();
                root = id3.mountTree(samples, "result", attributes, attributeSelectionMethod);
                this.tvDecision.Nodes.Add(root);
                test(testsamples);
                this.richTextBox1.Text += "第" + (i+1) +"部分测试"+ "\n";
                this.richTextBox1.Text += "测试样例的总数为：" + total + "\n";
                this.richTextBox1.Text += "正确样例的总数为：" + right + "\n";
                this.richTextBox1.Text += "准确率为：" + (double)right / (double)total + "\n";
                average += (double)right / (double)total;
                total = 0;
                right = 0;
                wrong = 0;
                }
                average = average / 10;
                this.richTextBox1.Text += "平均准确率为：" + average + "\n";
                average = 0;
        }

        //测试样本
        private void test(DataTable dt)
        {
            right = wrong = 0;
            total = dt.Rows.Count;
            foreach (DataRow aRow in dt.Rows)
            {
                traverse(aRow, this.tvDecision.Nodes[0], "result");
            }

        }

        //取出树节点的属性值，即括号内的值
        private string getLatterValue(string node)
        {
            string value = string.Empty;
            int index = node.IndexOf('(');
            if (index < 0)
                value = node;
            else
            {
                value = node.Substring(index + 1);
                value = value.Substring(0, value.Length - 1);//滤去最后的")"
            }
            return value;
        }

          //取出树节点的属性名称，即括号内前面的值
        private string getFrontValue(string node)
        {
            string value = string.Empty;
            int index = node.IndexOf('(');
            if (index > 0)
                value = node.Substring(0, index);
            else
                value = node;
            return value;
        }
        
        //
        private void traverse(DataRow aRow, TreeNode node, string targetAttribute)
        {
            //right = wrong = 0;
            TreeNode t = new TreeNode();
            string attribute = getFrontValue(node.Text);
            if (node.Nodes.Count != 0)
            {
                foreach (TreeNode n in node.Nodes)
                {
                    string value = getLatterValue(n.Text);
                    if (value.Equals(aRow[attribute]))
                        traverse(aRow, n, "result");
                }
            }
            else
            {
                t.Text = getFrontValue(node.Text);
            }

            if (t.Text.Equals(aRow[targetAttribute]))
            {
                t.Text = "";
                right++;
            }
            //else
            //    wrong++;


        }

        //创建一个DataTable，用于存储训练样例集
        private DataTable getDataTable()
        {   
            
            DataTable examples = new DataTable("samples");
            DataColumn column = examples.Columns.Add("A"+1);
            column.DataType = typeof(string);
            for (int i = 2; i < txtWidth; i++)
            {
                column = examples.Columns.Add("A"+i);
                column.DataType = typeof(string);

            }
            column = examples.Columns.Add("result");
            column.DataType = typeof(string);
            return examples;
        }

        //为DataTable填充数据
        private void addRowsToDataTable(DataTable dt, string dataline)
        {
            string[] data = dataline.Split(',');
            DataRow dr = dt.NewRow();
            for (int i = 0; i < txtWidth-1;i++ )
            {
                dr["A"+(i+1)] = data[i];
            }
            dr["result"] = data[txtWidth - 1];
            dt.Rows.Add(dr);
        }

        //填入数据进入数据表
      public void  fillData(int j)
        {
            samples.Clear();
            testsamples.Clear();
            string[] strArr = RollCall(textBox1.Text);
            for (int i = 0; i < j * (strArr.Length / 10); i++)
            {
                string str = System.Text.RegularExpressions.Regex.Replace(strArr[i], @"\s+", ","); //","替换空格串
                addRowsToDataTable(samples, str);
            }
            for (int i = (j + 1) * (strArr.Length / 10); i < strArr.Length; i++)
            {
                string str = System.Text.RegularExpressions.Regex.Replace(strArr[i], @"\s+", ","); //","替换空格串
                addRowsToDataTable(samples, str);
            }
            for (int i = j * (strArr.Length / 10); i < (j+1)*(strArr.Length / 10); i++)
            {
                string str = System.Text.RegularExpressions.Regex.Replace(strArr[i], @"\s+", ","); //","替换空格串
                addRowsToDataTable(testsamples, str);
            }
            
        }

      bool IsContain(ArrayList indexList, int index)
      {
          for (int i = 0; i < indexList.Count; i++)
          {
              int tempIndex = Convert.ToInt32(indexList[i]);
              if (tempIndex == index)
              {
                  return true;
              }
          }
          return false;
      }
        //填入属性值
      public void attributeValue()
      {
          Attribute[] attribute = new Attribute[txtWidth - 1];
          for (int i = 0; i < txtWidth - 1; i++)
          {

              attribute[i] = new Attribute("A" + (i + 1), gainAttributeValue(i + 1));
          }
          attributes = attribute;
          //Attribute A1 = new Attribute("A1", ginAttributeValue(1));
          //Attribute A2 = new Attribute("A2", new string[] { "6", "7", "8", "9", "10" });
          //Attribute A3 = new Attribute("A3", new string[] { "11", "12", "13", "14", "15" });
          // Attribute A4 = new Attribute("A4", new string[] { "16", "17", "18", "19", "20" });
          //attributes = new Attribute[] { A1, A2, A3, A4 };
      }

        //获取属性值
        public string[] gainAttributeValue(int list)
        {   
            string[] numbers = new string[15000];
            for (int i=0;i<txtHigh;i++)
            {
                numbers[i]=cellData[i, list - 1];
            }
            string[] listAttributeValue = RemoveDup(numbers);
            //删除null数组元素值
            string[] listValue = new string[listAttributeValue.Length-1];
            for (int j = 0; j < listAttributeValue.Length - 1;j++ )
            {
                listValue[j] = listAttributeValue[j];
            }
            return listValue;
        }

        //去除数组中重复项
        public static String[] RemoveDup(String[] values)
   {
        string[] result = values.Distinct().ToArray();
        return result;

   } 

    }
}
